package com.dongnao.jack.registry.handler;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.dongnao.jack.spring.parse.RegistryConfig;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisException;

/**
 * 
 * @ClassName: JedisRegistryConnection 
 * @Description: 用于service向redis中注册，注册的格式为  
 * 类名：｛hostAndIp:注册服务器的ip:host,
 *      注册协议protocol：protocol实例，
 *      spring容器的id  ref:ref    ｝
 *      
 *      注册的redis存储类型为redis
 * @author xuyp
 * @date 2018年4月20日 下午2:13:29 
 *
 */
public class JedisRegistryConnection implements RegistryConnection {

    private static Logger logger = LoggerFactory.getLogger(JedisRegistryConnection.class);

    private String supportFlag = "redis";

    private static RegistryConfig config;

    private static JedisPool jedisPool;

    @Override
    public String getValue(String key) {
        String value = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            if (jedis.exists(key)) {
                value = jedis.get(key);
                value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
            }
        }
        catch (final Exception e) {}
        finally {
            returnResource(jedis);
        }
        return value;
    }

    public boolean lpush(String key, JedisServiceConfigBean bean) {
        Jedis jedis = null;
        try {
            jedis = getResource();

            List<String> lrange = jedis.lrange(key, 0, -1);

            for (String string : lrange) {
                JedisServiceConfigBean parseObject = JSONObject.parseObject(string, JedisServiceConfigBean.class);

                if (parseObject.getHostAndIp().equals(bean.getHostAndIp())
                        && parseObject.getRef().equals(bean.getRef())) {

                    jedis.lrem(key, 0, string);

                }

            }

            jedis.lpush(key, JSONObject.toJSONString(bean));
            return true;

        }
        catch (final Exception e) {
            return false;
        }
        finally {
            returnResource(jedis);
        }
    }

    public List<JedisServiceConfigBean> lrange(String key) {
        Jedis jedis = null;
        try {
            jedis = getResource();

            List<String> lrange = jedis.lrange(key, 0, -1);
            List<JedisServiceConfigBean> beanList = new ArrayList<>(lrange.size());
            for (String string : lrange) {
                JedisServiceConfigBean parseObject = JSONObject.parseObject(string, JedisServiceConfigBean.class);

                beanList.add(parseObject);

            }

            return beanList;

        }
        catch (final Exception e) {}
        finally {
            returnResource(jedis);
        }
        return null;
    }

    private JedisRegistryConnection(RegistryConfig config) {
        super();
        setConfig(config);
        if (config != null && support(config.getProtocol())) {
            String address = config.getAddress();
            String[] split = address.split(":");
            jedisPool = new JedisPool(split[0], Integer.parseInt(split[1]));
        }
    }

    @Override
    public void put(String key, String value) {
        String result = null;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.set(key, value);
            logger.debug("set {} = {}", key, value);
        }
        catch (final Exception e) {
            logger.warn("set {} = {}", key, value, e);
        }
        finally {
            returnResource(jedis);
        }

    }

    @Override
    public boolean support(String configName) {
        return supportFlag.equals(configName);
    }

    public static RegistryConnection createInstance(RegistryConfig config) {

        setConfig(config);
        return JedisRegistryConnection.JedisFactory.instance;
    }

    private static class JedisFactory {

        public static JedisRegistryConnection instance = new JedisRegistryConnection(config);
    }

    public static RegistryConfig getConfig() {
        return config;
    }

    public static void setConfig(RegistryConfig config) {
        JedisRegistryConnection.config = config;
    }

    /**
     * 获取资源
     *
     * @return
     * @throws JedisException
     */
    public static Jedis getResource() throws JedisException {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            // logger.debug("getResource.", jedis);
        }
        catch (final JedisException e) {
            logger.warn("getResource.", e);
            returnBrokenResource(jedis);
            throw e;
        }
        return jedis;
    }

    /**
     * 归还资源
     *
     * @param jedis
     * @param isBroken
     */
    public static void returnBrokenResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnBrokenResource(jedis);
        }
    }

    /**
     * 释放资源
     *
     * @param jedis
     * @param isBroken
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }

    public static void main(String[] args) {

        RegistryConfig config1 = new RegistryConfig();
        config1.setProtocol("redis");
        config1.setAddress("192.168.2.49:6379");
        RegistryConnection connection = JedisRegistryConnection.createInstance(config1);
        System.out.println(connection);
        System.out.println(connection.getValue("name"));
        connection.put("name", "123");
        String value = connection.getValue("name");
        System.out.println(value);

    }

    @Override
    public boolean lpush(String key, String jsonObject) {
        return lpush(key, JSONObject.parseObject(jsonObject, JedisServiceConfigBean.class));

    }

    @Override
    public String lrangeString(String key) {
        List<JedisServiceConfigBean> list = lrange(key);
        return JSONObject.toJSONString(list);
    }
}
